<?php
/**
 * Base entity class that all our entities will inherit from
 *
 * @package    Custom_Model
 * @version    $Id:$
 */
abstract class Custom_Model_EntityAbstract 
        extends Zend_Db_Table_Abstract 
        implements Custom_Model_EntityInterface
{
    
    /**
     * Returns an instance of a Zend_Db_Table_Select object
     * 
     * @param array $options
     * @see Custom/Db/Table/Custom_Db_Table_Interface::select()
     * @return boolean
     */
    public function select($options = null)
    {
        // Setting IntegrityCheck to false skips the checks for table joins, 
        // allowing 'hybrid' table rows to be created.
        $select = parent::select($options)->setIntegrityCheck(false);
        return $select;
    }
    /**
     * Save a row to the database
     *
     * @param array             $info The data to insert/update
     * @param Zend_DB_Table_Row $row Optional The row to use
     * @return mixed The primary key
     */
    public function saveRow($info, $row = null)
    {
        if (null === $row) {
            $row = $this->createRow();
        }

        $columns = $this->info('cols');
        foreach ($columns as $column) {
            if (array_key_exists($column, $info)) {
                $row->$column = $info[$column];
            }
        }
        return $row->save();
    }

    /**
     * Fetch the data to paginator adaptor
     *
     * @param array $filters Filtering conditions OPTIONAL
     * @param string $sortField Sorting conditions OPTIONAL
     * 
     * @return Zend_Paginator_Adapter_DbTableSelect
     */
    public function fetchPaginationAdaptor($filters = null, $sortField = null)
    {
        $select = $this->select();
         
        //add any filters which are set
        if (count($filters) > 0) {
            foreach ($filters as $field => $filter) {
                if (null != $filter) {
                    $whereCond = $this->getAdapter()
                                      ->quoteInto($field . ' = ?', $filter);
                    $select->where($whereCond);
                }
            }
        }

        //add the sort field if it is set
        if (null != $sortField) {
            $select->order($sortField);
        }
        //create a new instance of the paginator adaptor and return it
        $adapter = new Zend_Paginator_Adapter_DbTableSelect($select);
        return $adapter;
    }

    /**
     * Returns the name of the table
     *
     * @return string
     */
    public function getTableName ()
    {
        return $this->_name;
    }

    /**
     * Magic finder method!
     *
     * @param string $method
     * @param array $args
     * @return int
     * @throws Zend_Exception
     */
    public function __call ($method, array $args)
    {
        if (preg_match('/^findBy(\w+?)$/', $method, $matches)) {
            return $this->fetchAll($this->buildWhere(explode('And', $matches[1]), $args));
        }

        if (preg_match('/^findOneBy(\w+?)$/', $method, $matches)) {
            return $this->fetchRow($this->buildWhere(explode('And', $matches[1]), $args));
        }

        throw new Zend_Db_Table_Exception('Unrecognized method '.$method.'');
    }

    /**
     * Get data from cache by $cacheType
     * $cacheType is one of following values:
     * - 'dbschema' cache for database schema
     * - 'normal' cache normal, will automatic be cleared 
     * 		after timeout (15 minutes by default config)
     * - 'persistent' cache with no timeout, just be cleared manually 
     * 
     * @param string $cacheType
     * @return cache
     */
 	protected function _getCache($cacheType)
    {
        /*try {
            if (Zend_Registry::isRegistered('cachemanager')) {
                $cacheManager = Zend_Registry::get('cachemanager');
                $cache = $cacheManager->getCache($cacheType);
            } else {
                $cache = null;
            }
            
        } catch (Exception $e) {
            $cache = null;
        }
        return $cache;*/
    }
    
    /**
     * Clear cache by tags (just clear persistent cache)
     * 
     * @param array $tags
     */
    protected function _clearCacheByTags($tags)
    {    	
    	/*$persistentCache = $this->_getCache(self::CACHE_TYPE_PERSISTENT);
    	if (null != $persistentCache) {
	    	$persistentCache->clean(
			    Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
			    $tags);		
    	}
    	
    	$normalCache = $this->_getCache(self::CACHE_TYPE_NORMAL);
    	if (null != $normalCache) {
	    	$normalCache->clean(
			    Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG,
			    $tags);		
    	}*/
    }
    
    /**
     * Takes an array of keys => values and converts it to an array of sql statements
     *
     * @param array $keys
     * @param array $args
     * @return array
     */
    private function _buildWhere ($keys, $args)
    {
        if (count($keys) != count($args)) {
            throw new Zend_Db_Table_Exception('Argument count does not match key count!');
        }

        $whereSql = array();

        $constraints = array_combine($keys, $args);

        foreach ($constraints as $key => $value) {
            $whereSql[] = $this->getAdapter()->quoteInto($key . ' = ?', $value);
        }
        return $whereSql;
    }

    /**
     * Quick method to efficiently count the number of records in a table.
     * Has support for SQL WHERE in the form of a standard WHERE clause
     * or an associative array.
     *
     * @param string|array $where
     * @return int
     */
    public function count($where = null)
    {
        $select = $this->select();
        $select->from($this->_name, 'COUNT(*) as numcount');
        if ($where) {
            if (is_array($where)) {
                $select->where(implode(' AND ', $this->_buildWhere(array_keys($where), array_values($where))));
            } else {
                $select->where($where);
            }
        }
        return $this->fetchRow($select)->numcount;
    }

    /**
     * Quotes a value and places into a piece of text at a placeholder. This is
     * wrappered from Zend_Db_Adapter_Abstract.quoteInto function
     *
     * The placeholder is a question-mark; all placeholders will be replaced
     * with the quoted value.   For example:
     *
     * <code>
     * $text = "WHERE date < ?";
     * $date = "2005-01-02";
     * $safe = $sql->quoteInto($text, $date);
     * // $safe = "WHERE date < '2005-01-02'"
     * </code>
     *
     * @param string  $text  The text with a placeholder.
     * @param mixed   $value The value to quote.
     * @param string  $type  OPTIONAL SQL datatype
     * @param integer $count OPTIONAL count of placeholders to replace
     * @return string An SQL-safe quoted value placed into the original text.
     */
    public function quoteInto($text, $value, $type = null, $count = null)
    {
        return $this->getAdapter()->quoteInto($text, $value, $type, $count);
    }
}